package com.cysyz.module.log.business.aspect;


import com.cysyz.module.log.business.annotation.BusinessLogInfo;
import com.cysyz.module.log.business.domain.SysBusinessLog;
import com.cysyz.module.support.service.BaseService;
import com.cysyz.mylib.myfilter.MyFilter;
import com.cysyz.mylib.myfilter.impl.SimpleMyFilter;
import com.cysyz.mylib.myfilter.matcher.Matcher;
import com.cysyz.mylib.utils.MyReflectionUtils;
import com.cysyz.mylib.utils.PropertiesUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

@Aspect
public class BusinessLogPersistAspect extends BaseService {
    MyFilter methodNameFilter;

    public BusinessLogPersistAspect() {
        Collection includes =new ArrayList();
        String excludesCsv = (String) PropertiesUtil.getProperties(BusinessLogPersistAspect.class.getResource("/business_log_method.properties").getFile()).get("excludes");

        final Map<String, Pattern> patternsMap =  new HashMap<>();

        List<String> excludes = Arrays.asList(excludesCsv.split(","));

        for (String exclude : excludes) {
            patternsMap.put(exclude, Pattern.compile(exclude.trim()));
        }

        methodNameFilter = new SimpleMyFilter(new Matcher() {
            @Override
            public boolean match(Object target, Object includeOrExcludeVal) {
                Pattern pattern = patternsMap.get(includeOrExcludeVal);

                return pattern.matcher((CharSequence) target).matches();
            }
        }, includes, excludes);
    }


    private void pointCutMethod() {
    }


    //声明环绕通知  
  /*  @Around("pointCutMethod()")*/
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        Object o = pjp.proceed();

        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();

        if (!BaseController.class.isAssignableFrom(method.getDeclaringClass())) {
            throw new IllegalStateException("BusinessLogPersistAspect can only intercept the Controller class which inherit from BaseController");
        }

        ModuleFunction moduleFunction = MyReflectionUtils.getAnnotation(method, ModuleFunction.class);
        if(methodNameFilter.filter(method.getName()) && moduleFunction != null && moduleFunction.moduleFunctionType() == ModuleFunctionType.NORMAL) {
            if (!method.isAnnotationPresent(BusinessLogInfo.class)) {
                throw new IllegalStateException("the Controller which want to be businesslogable must be @BusinessLogInfo annotationed:[" + method.getDeclaringClass().getName() + "." + method.getName() + "]" + ". if do not want to let this method be loged, you can config business_log_method.properties file.");
            }

            BusinessLogInfo businessLogAnnotation = method.getAnnotation(BusinessLogInfo.class);

            SysBusinessLog businessLog = new SysBusinessLog();
            businessLog.setOperationName(businessLogAnnotation.operationName());
            businessLog.setBusinessLogType(businessLogAnnotation.businessLogType());

            SysUser currentLoginAdmin = SessionData.getCurrentLoginSysUser();
            businessLog.setOperator(currentLoginAdmin);
            businessLog.setOperateDate(new Date());
            businessLog.setExtraMessage((String) ServletActionContext.getContext().get(SysConstants.BusinessLog.BUSINESSLOG_MESSAGE));
            this.save(businessLog);
            ServletActionContext.setBusinessLog(businessLog);
        }

        return o;
    }

} 